package com.ruoyi.recyclecomprehensive.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.recycle.domain.*;
import com.ruoyi.recycle.dto.HousekeepingOrderQueryDTO;
import com.ruoyi.recycle.dto.RecycleOrderDTO;
import com.ruoyi.recycle.exception.BusinessException;
import com.ruoyi.recycle.service.*;
import com.ruoyi.recyclecomprehensive.annotion.CheckUser;
import com.ruoyi.recyclecomprehensive.dto.RecordFeesDTO;
import com.ruoyi.recyclecomprehensive.dto.VerifyRecycleOrderDTO;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.*;
import java.util.stream.Collectors;

@RequestMapping("/order")
@RestController
@Api(tags = "订单管理")
@Slf4j
public class OrderController extends BaseController {
    @Autowired
    private IHousekeepingOrderService housekeepingOrderService;
    @Autowired
    private IRecycleOrderService recycleOrderService;
    @Autowired
    private IIntegralConfigService integralConfigService;
    @Autowired
    private IRecycleCommodityService commodityService;
    @Autowired
    private IHousekeepingCommodityService housekeepingCommodityService;
    @Autowired
    private IClientUserManagementService clientUserManagementService;
    @Autowired
    private IMerchantManagementService merchantManagementService;
    @Autowired
    private BillRecordService billRecordService;


    /**
     * 分页查询家政订单列表
     */
    @PostMapping("/housekeepingOrderPageQuery")
    @ApiOperation("分页查询家政订单列表")
    @CheckUser(isCheck = true)
    public IPage<HousekeepingOrder> housekeepingOrderPageQuery(@RequestBody HousekeepingOrderQueryDTO queryDTO) {
        final HousekeepingOrder order = new HousekeepingOrder();
        BeanUtils.copyProperties(queryDTO, order);
        final LambdaQueryWrapper<HousekeepingOrder> wrapper = Wrappers.lambdaQuery(order).orderByDesc(HousekeepingOrder::getCreatedTime);
        if (queryDTO.getSearchTimeBegin() != null) {
            wrapper.ge(HousekeepingOrder::getCreatedTime, queryDTO.getSearchTimeBegin());
        }
        if (queryDTO.getSearchTimeEnd() != null) {
            wrapper.le(HousekeepingOrder::getCreatedTime, queryDTO.getSearchTimeEnd());
        }
        final Page<HousekeepingOrder> page = housekeepingOrderService.page(new Page<HousekeepingOrder>()
                .setCurrent(queryDTO.getCurrentPage())
                .setSize(queryDTO.getPageSize()), wrapper);
        final List<HousekeepingOrder> records = page.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            final List<Long> ids = records.stream().map(HousekeepingOrder::getClientId).collect(Collectors.toList());
            final Map<Long, String> clientNames = getClientName(ids);
            for (HousekeepingOrder orderInfo : records) {
                orderInfo.setCreatedBy(clientNames.get(orderInfo.getClientId()));
            }
            page.setRecords(records);
        }
        return page;
    }

    /**
     * 获取家政订单详细信息
     */
    @GetMapping(value = "/HKOrderNo")
    @ApiOperation("获取家政订单详细信息")
    @ApiImplicitParam(name = "HKOrderNo", value = "家政订单订单号")
    public R<HousekeepingOrder> getHouseKeepingOrderInfo(@RequestParam String HKOrderNo) {
        final HousekeepingOrder order = housekeepingOrderService.getById(HKOrderNo);
        List<HousekeepingCommodity> commodities = new ArrayList<>();
        if (Objects.nonNull(order)) {
            final String clientName = getClientName(ListUtil.toList(order.getClientId())).get(order.getClientId());
            order.setCreatedBy(clientName);
            commodities = housekeepingCommodityService
                    .list(Wrappers.lambdaQuery(new HousekeepingCommodity()).in(HousekeepingCommodity::getHousekeepingId, HKOrderNo));
        }

        return R.ok(order.setCommodityList(commodities));
    }

    /**
     * 修改家政订单
     */
    @Log(title = "家政订单", businessType = BusinessType.UPDATE)
    @PostMapping("/editOrder")
    @ApiOperation("修改家政订单")
    public R<Boolean> editingHouseKeepingOrder(@RequestBody HousekeepingOrder housekeepingOrder) {
        return R.ok(housekeepingOrderService.updateById(housekeepingOrder));
    }

    @PostMapping("/recordFees")
    @ApiOperation("输入家政服务订单价格")
    @GlobalTransactional(rollbackFor = Exception.class)
    public R<Boolean> recordFees(@RequestBody RecordFeesDTO recordDTO) {
        final List<RecordFeesDTO.RecordFees> feesList = recordDTO.getFees();
        final String loginUserName = SecurityUtils.getUsername();
        List<HousekeepingCommodity> commodities = new ArrayList<>(feesList.size());
        BigDecimal orderPrice = BigDecimal.ZERO;
        for (RecordFeesDTO.RecordFees fees : feesList) {
            Assert.isTrue(Objects.nonNull(fees.getPrice()),
                    () -> new BusinessException(StrUtil.format("请输入{0}的价格", fees.getServiceName())));
            commodities.add(new HousekeepingCommodity()
                    .setUpdatedBy(loginUserName)
                    .setId(fees.getServiceId())
                    .setMoney(fees.getPrice())
                    .setName(fees.getServiceName()));
            orderPrice = orderPrice.add(fees.getPrice());

        }
        housekeepingOrderService.updateById(new HousekeepingOrder()
                .setHKOrderNo(recordDTO.getOrderNo())
                .setStatus(recordDTO.getOrderStatus())
                .setUpdatedBy(loginUserName)
                .setPracticalMoney(orderPrice));
        housekeepingCommodityService.updateBatchById(commodities);
        return R.ok(true);
    }

    @PostMapping("/editRecycleOrder")
    @ApiOperation("修改回收订单")
    public R<Boolean> editingRecycleOrder(@RequestBody RecycleOrder recycleOrder) {
        return R.ok(recycleOrderService.updateById(recycleOrder));
    }

    /**
     * 分页查询回收订单
     */
    @PostMapping("/recycleOrderPageQuery")
    @ApiOperation("分页查询回收订单")
    @CheckUser(isCheck = true)
    public IPage<RecycleOrder> pageQuery(@RequestBody RecycleOrderDTO queryDTO) {
        final RecycleOrder recycleOrder = new RecycleOrder();
        BeanUtils.copyProperties(queryDTO, recycleOrder);
        final LambdaQueryWrapper<RecycleOrder> wrapper = Wrappers.lambdaQuery(recycleOrder)
                .orderByDesc(RecycleOrder::getCreatedTime);
        if (queryDTO.getSearchTimeBegin() != null) {
            wrapper.ge(RecycleOrder::getCreatedTime, queryDTO.getSearchTimeBegin());
        }
        if (queryDTO.getSearchTimeEnd() != null) {
            wrapper.le(RecycleOrder::getCreatedTime, queryDTO.getSearchTimeEnd());
        }
        final Page<RecycleOrder> page = recycleOrderService.page(new Page<RecycleOrder>()
                .setCurrent(queryDTO.getCurrentPage())
                .setSize(queryDTO.getPageSize()), wrapper);
        final List<RecycleOrder> records = page.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            final List<Long> clients = records.stream().map(RecycleOrder::getClientId).collect(Collectors.toList());
            final Map<Long, String> clientName = getClientName(clients);
            for (RecycleOrder order : records) {
                order.setCreatedBy(clientName.get(order.getClientId()));
            }
            page.setRecords(records);
        }

        return page;
    }

    /**
     * 获取回收订单详细信息
     */
    @GetMapping(value = "/recycleOrderNo")
    @ApiOperation("获取回收订单详细信息")
    @ApiImplicitParam(name = "recycleOrderNo", value = "id")
    public R<RecycleOrder> getInfo(@RequestParam String recycleOrderNo) {
        final RecycleOrder recycleOrder = recycleOrderService.getById(recycleOrderNo);
        List<RecycleCommodity> commodities = new ArrayList<>();
        if (Objects.nonNull(recycleOrder)) {
            final Map<Long, String> clientName = getClientName(ListUtil.toList(recycleOrder.getClientId()));
            recycleOrder.setCreatedBy(clientName.get(recycleOrder.getClientId()));
            commodities = commodityService.list(Wrappers.lambdaQuery(new RecycleCommodity()).in(RecycleCommodity::getOrderId, recycleOrderNo));
        }

        return R.ok(recycleOrder.setCommodities(commodities));
    }

    @ApiOperation("计算积分转换")
    @GetMapping("/getRecycleIntegral")
    @ApiImplicitParam(value = "重量", name = "weight")
    public R<Long> getRecycleIntegral(@RequestParam BigDecimal weight) {
        final IntegralConfig recycleRule = integralConfigService.getOne(Wrappers.lambdaQuery(new IntegralConfig())
                .eq(IntegralConfig::getType, "1"));
        if (recycleRule == null) {
            return R.fail("找不到积分转换规则");
        }
        final BigDecimal integral = weight.multiply(BigDecimal.valueOf(recycleRule.getIntegral()), MathContext.UNLIMITED);
        return R.ok(integral.longValue());
    }

    /**
     * 输入回收订单重量
     */
    @PostMapping("/verifyRecycleOrder")
    @ApiOperation("验货")
    @GlobalTransactional(rollbackFor = Exception.class)
    @SneakyThrows
    public R<Boolean> editRecycleOrder(@RequestBody VerifyRecycleOrderDTO verifyDTO) {
        log.info("验货接收的请求内容为:{}", JSON.toJSONString(verifyDTO));
        final Long userId = SecurityUtils.getUserId();
        final RecycleOrder order = recycleOrderService.getById(verifyDTO.getRecycleOrderNo());
        if (StrUtil.equals(order.getStatus(), "6")) {
            return R.fail("该订单订单已结算");
        }
        final MerchantManagement account = merchantManagementService.getOne(Wrappers.lambdaQuery(new MerchantManagement())
                .eq(MerchantManagement::getUserId, userId));
        Assert.isTrue(Objects.nonNull(account), () -> new BusinessException("找不到符合的综合站账号"));
        final Long integral = verifyDTO.getIntegral();
        final Long accountIntegral = account.getIntegral();
        Long compare = accountIntegral - integral;
        if (compare < 0) {
            return R.fail("蓝硬币不足 请充值");
        }
        BigDecimal practicalWeight = BigDecimal.ZERO;
        final List<VerifyRecycleOrderDTO.VerifyRecycleCommodity> commodities = verifyDTO.getCommodities();
        if (CollUtil.isNotEmpty(commodities)) {
            for (VerifyRecycleOrderDTO.VerifyRecycleCommodity commodity : commodities) {
                practicalWeight = practicalWeight.add(commodity.getWeight());
            }
            final List<RecycleCommodity> collect = commodities.stream().map(c -> new RecycleCommodity()
                    .setId(c.getId())
                    .setUpdatedBy(verifyDTO.getUpdateBy())
                    .setPracticalWeight(c.getWeight())
                    .setImg(c.getPictureUrl())).collect(Collectors.toList());
            commodityService.updateBatchById(collect);
        }
        recycleOrderService.updateById(order.setStatus(verifyDTO.getOrderStatus())
                .setUpdatedBy(verifyDTO.getUpdateBy())
                .setPracticalWeight(practicalWeight));
        final ClientUserManagement client = clientUserManagementService.getById(order.getClientId());
        clientUserManagementService.updateById(client.setIntegral(client.getIntegral() + integral));
        merchantManagementService.updateById(account.setIntegral(account.getIntegral() - integral));
        billRecordService.save(new BillRecord().setOutput(BigDecimal.valueOf(integral))
                .setOrderNo(order.getRecycleOrderNo())
                .setUserId(account.getUserId())
                .setAccount(account.getMerchantNumber())
                .setType(2)
                .setUserType(2));
        return R.ok(true, "验货成功");

    }

    private Map<Long, String> getClientName(List<Long> ids) {
        final List<ClientUserManagement> clients = clientUserManagementService.listByIds(ids);
        Map<Long, String> names = new HashMap<>();
        if (CollUtil.isNotEmpty(clients)) {
            for (ClientUserManagement client : clients) {
                names.put(client.getId(), client.getUserName());
            }
        }

        return names;
    }

    @PostMapping("/settle")
    @ApiOperation("回收订单结算")
    @GlobalTransactional(rollbackFor = Exception.class)
    public R<Boolean> settle(@RequestBody RecycleOrder recycleOrder) {
        final Long clientId = recycleOrder.getClientId();
        final Integer integral = recycleOrder.getIntegral();
        if (Objects.isNull(integral)) {
            return R.ok(recycleOrderService.updateById(recycleOrder));
        }
        final Long merchantId = recycleOrder.getMerchantId();
        final MerchantManagement merchant = merchantManagementService.getById(merchantId);
        final Long merchantBlueCoins = merchant.getIntegral();
        if (Objects.isNull(merchantBlueCoins) || merchantBlueCoins.equals(0)) {
            return R.fail("您的账户蓝星币余额为零,请充值");
        }
        if (integral > merchantBlueCoins) {
            return R.fail("您的账号蓝星币余额不足以支付该订单,请充值");
        }
        merchantManagementService.updateById(merchant.setIntegral(merchant.getIntegral() - integral));
        final ClientUserManagement client = clientUserManagementService.getById(clientId);
        clientUserManagementService.updateById(client.setIntegral(client.getIntegral() + integral));
        return R.ok(recycleOrderService.updateById(recycleOrder));


    }
}
